
package com.shop.cloud.mall.api.controller;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.shop.cloud.common.core.constant.SecurityConstants;
import com.shop.cloud.common.core.util.LocalDateTimeUtils;
import com.shop.cloud.common.core.util.R;
import com.shop.cloud.common.data.tenant.TenantContextHolder;
import com.shop.cloud.common.portal.annotation.ApiLogin;
import com.shop.cloud.common.portal.constant.PortalConstants;
import com.shop.cloud.common.portal.entity.ThirdSession;
import com.shop.cloud.common.portal.util.ThirdSessionHolder;
import com.shop.cloud.mall.api.service.VipCostService;
import com.shop.cloud.mall.api.service.VipTypeService;
import com.shop.cloud.mall.api.service.VipUserRechargeService;
import com.shop.cloud.mall.common.config.MallConfigProperties;
import com.shop.cloud.mall.common.constant.MallConstants;
import com.shop.cloud.mall.common.constant.MallReturnCode;
import com.shop.cloud.mall.common.entity.VipCost;
import com.shop.cloud.mall.common.entity.VipType;
import com.shop.cloud.mall.common.entity.VipUserRecharge;
import com.shop.cloud.pay.common.dto.AliBaseRequest;
import com.shop.cloud.pay.common.entity.PayConfig;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 用户会员充值
 *
 * @author
 * @date 2024-03-19 15:24:20
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/vipuserrecharge")
@Tag(description = "vipuserrecharge", name = "用户会员充值API")
public class VipUserRechargeController {

    private final VipUserRechargeService vipUserRechargeService;
    private final com.shop.cloud.pay.common.feign.FeignPayService feignPayService;
    private final VipTypeService vipTypeService;
    private final VipCostService vipCostService;
    private final MallConfigProperties mallConfigProperties;

    /**
     * 用户会员充值分页列表
     * @param page 分页对象
     * @param vipUserRecharge 用户会员充值
     * @return
     */
    @Operation(summary = "用户会员充值分页列表")
    @GetMapping("/page")
    public R getPage(Page page, VipUserRecharge vipUserRecharge) {
        vipUserRecharge.setUserId(ThirdSessionHolder.getUserId());
        return R.ok(vipUserRechargeService.page2(page, vipUserRecharge));
    }

    /**
     * 用户会员充值查询
     * @param id
     * @return R
     */
    @Operation(summary = "用户会员充值查询")
    @GetMapping("/{id}")
    public R getById(@PathVariable("id") String id) {
        return R.ok(vipUserRechargeService.getById(id));
    }

    /**
     * 用户会员充值新增
     * @param vipUserRecharge 用户会员充值
     * @return R
     */
    @Operation(summary = "用户会员充值新增")
    @PostMapping
    @ApiLogin
    public R save(@RequestBody VipUserRecharge vipUserRecharge) {
        vipUserRecharge.setUserId(ThirdSessionHolder.getUserId());
        VipCost vipCost = vipCostService.getById(vipUserRecharge.getVipCostId());
        //计算支付金额
        vipUserRecharge.setPaymentPrice(vipCost.getSalesPrice().multiply(new BigDecimal(vipUserRecharge.getCount())));
        vipUserRecharge.setTradeNo(IdUtil.getSnowflake(0,0).nextIdStr());
        vipUserRechargeService.save(vipUserRecharge);
        return R.ok(vipUserRecharge);
    }

    /**
     * 统一下单，支付会员充值
     * @param vipUserRecharge
     * @return
     */
    @Operation(summary = "统一下单，支付会员充值")
    @PostMapping("/unified")
    @ApiLogin
    public R unifiedVipUserRecharge(HttpServletRequest request, @RequestBody VipUserRecharge vipUserRecharge) {
        String tradeType = vipUserRecharge.getTradeType();
        String paymentType = vipUserRecharge.getPaymentType();
        String quitUrl = vipUserRecharge.getQuitUrl();
        String returnUrl = vipUserRecharge.getReturnUrl();
        String appId = vipUserRecharge.getAppId();
        if(StrUtil.isBlank(paymentType)){
            return R.failed(MallReturnCode.ERR_70002.getCode(), MallReturnCode.ERR_70002.getMsg());
        }
        vipUserRecharge = vipUserRechargeService.getById(vipUserRecharge.getId());
        //获取支付配置
        R<PayConfig> r = feignPayService.getPayConfigByType(paymentType, SecurityConstants.FROM_IN);
        if(!r.isOk()){
            return R.failed(r.getMsg());
        }
        PayConfig payConfig = r.getData();
        if(payConfig == null){
            return R.failed("支付未配置");
        }
        VipType vipType = vipTypeService.getById(vipUserRecharge.getVipTypeId());
        String body = "支付会员：" + vipType.getVipName();
        body = body.length() > 40 ? body.substring(0,39) : body;
        //微信支付
        if(MallConstants.ORDER_PAYMENT_TYPE_1.equals(paymentType)){
            ThirdSession thirdSession = ThirdSessionHolder.getThirdSession();
            WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = new WxPayUnifiedOrderRequest();
            wxPayUnifiedOrderRequest.setSubMchId(payConfig.getSpecialMchId());
            wxPayUnifiedOrderRequest.setBody(body);
            wxPayUnifiedOrderRequest.setOutTradeNo(vipUserRecharge.getTradeNo());
            wxPayUnifiedOrderRequest.setTotalFee(vipUserRecharge.getPaymentPrice().multiply(new BigDecimal(100)).intValue());
            wxPayUnifiedOrderRequest.setTradeType(tradeType);
            wxPayUnifiedOrderRequest.setNotifyUrl(mallConfigProperties.getNotifyHost()+MallConstants.SERVER_ROUTE_NAME_MALLAPI + PortalConstants.VIPUSERRECHARGE_NOTIFY_URL_WX+"/"+vipUserRecharge.getTenantId());
            wxPayUnifiedOrderRequest.setSpbillCreateIp(request.getRemoteAddr());
            wxPayUnifiedOrderRequest.setSubOpenid(thirdSession.getOpenId());
            wxPayUnifiedOrderRequest.setSubAppId(thirdSession.getAppId());
            wxPayUnifiedOrderRequest.setAppid(appId);
            return feignPayService.unifiedOrderWx(wxPayUnifiedOrderRequest, SecurityConstants.FROM_IN);
        }else if(MallConstants.ORDER_PAYMENT_TYPE_2.equals(paymentType)){//支付宝支付
            Map<String, Object> params = new HashMap<>();
            params.put("tradeType",tradeType);
            params.put("outTradeNo",vipUserRecharge.getTradeNo());
            params.put("totalAmount",vipUserRecharge.getPaymentPrice().toString());
            params.put("notifyUrl",mallConfigProperties.getNotifyHost()+MallConstants.SERVER_ROUTE_NAME_MALLAPI + PortalConstants.VIPUSERRECHARGE_NOTIFY_URL_ALI+"/" + vipUserRecharge.getTenantId());
            params.put("returnUrl",returnUrl);
            params.put("quitUrl",quitUrl);
            params.put("subject",body);
            AliBaseRequest aliBaseRequest = new AliBaseRequest();
            aliBaseRequest.setAppAuthToken(payConfig.getSpecialMchId());
            aliBaseRequest.setParams(params);
            return feignPayService.unifiedOrderAli(aliBaseRequest, SecurityConstants.FROM_IN);
        }else{
            return R.failed("无此支付类型");
        }
    }

    /**
     * 支付回调（微信）
     * @param xmlData
     * @return
     * @throws WxPayException
     */
    @Operation(summary = "支付回调（微信）")
    @PostMapping("/notify-wx/{tenantId}")
    public String notifyOrderWx(@RequestBody String xmlData, @PathVariable("tenantId") String tenantId) {
        log.info("支付回调（微信）:"+xmlData);
        TenantContextHolder.setTenantId(tenantId);//设置租户ID
        R<WxPayOrderNotifyResult> r = feignPayService.notifyOrderWx(xmlData, SecurityConstants.FROM_IN);
        if(r.isOk()){
            WxPayOrderNotifyResult notifyResult = r.getData();
            VipUserRecharge vipUserRecharge = vipUserRechargeService.getOne(Wrappers.<VipUserRecharge>lambdaQuery()
                    .eq(VipUserRecharge::getTradeNo,notifyResult.getOutTradeNo()));
            if(vipUserRecharge != null){
                vipUserRecharge.setTradeType(notifyResult.getTradeType());
                if(vipUserRecharge.getPaymentPrice().multiply(new BigDecimal(100)).intValue() == notifyResult.getTotalFee()){
                    String timeEnd = notifyResult.getTimeEnd();
                    LocalDateTime paymentTime = LocalDateTimeUtils.parse(timeEnd);
                    vipUserRecharge.setPaymentTime(paymentTime);
                    vipUserRecharge.setTransactionId(notifyResult.getTransactionId());
                    vipUserRecharge.setPaymentType(MallConstants.ORDER_PAYMENT_TYPE_1);
                    vipUserRechargeService.notifyVipUserRecharge(vipUserRecharge);
                    return WxPayNotifyResponse.success("成功");
                }else{
                    return WxPayNotifyResponse.fail("付款金额与订单金额不等");
                }
            }else{
                return WxPayNotifyResponse.fail("无此订单");
            }
        }else{
            return WxPayNotifyResponse.fail(r.getMsg());
        }
    }

    /**
     * 支付回调（支付宝）
     * @param request
     * @return
     * @throws
     */
    @Operation(summary = "支付回调（支付宝）")
    @ResponseBody
    @PostMapping("/notify-ali/{tenantId}")
    public String notifyOrderAli(HttpServletRequest request, @PathVariable("tenantId") String tenantId) {
        log.info("支付回调（支付宝）");
        Map<String, String> params = new HashMap<>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            params.put(name, valueStr);
        }
        String appId = request.getParameter("app_id");
        if(StrUtil.isBlank(appId)){
            return "appId不能为空";
        }
        TenantContextHolder.setTenantId(tenantId);//设置租户ID
        VipUserRecharge vipUserRecharge = vipUserRechargeService.getOne(Wrappers.<VipUserRecharge>lambdaQuery()
                .eq(VipUserRecharge::getTradeNo,request.getParameter("out_trade_no")));
        if(vipUserRecharge == null){
            log.error("无此订单out_trade_no："+request.getParameter("out_trade_no"));
            return "无此订单";
        }
        if(vipUserRecharge.getPaymentPrice().compareTo(new BigDecimal(request.getParameter("total_amount"))) == 0){
            LocalDateTime paymentTime = LocalDateTimeUtils.parse(request.getParameter("gmt_payment"));
            vipUserRecharge.setPaymentTime(paymentTime);
            vipUserRecharge.setTransactionId(request.getParameter("trade_no"));
            vipUserRecharge.setPaymentType(MallConstants.ORDER_PAYMENT_TYPE_2);
            vipUserRechargeService.notifyVipUserRecharge(vipUserRecharge);
            log.info("支付回调（支付宝）success");
            return "success";
        }else{
            log.error("付款金额与订单金额不等out_trade_no："+request.getParameter("out_trade_no"));
            return "付款金额与订单金额不等";
        }

    }

}
